package com.lingjtx.im.core.common;

import com.lingjtx.common.core.constant.RedisConfig;
import com.lingjtx.im.core.handle.AuthHandshakeHandler;
import com.lingjtx.im.core.handle.ExceptionHandler;
import com.lingjtx.im.core.handle.HeartbeatHandler;
import com.lingjtx.im.core.handle.WebSocketHandler;
import com.lingjtx.im.core.protocol.ProtocolDecoder;
import com.lingjtx.im.core.protocol.ProtocolEncoder;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.timeout.IdleStateHandler;
import org.springframework.stereotype.Component;

@ChannelHandler.Sharable
@Component
public class WebSocketChannelInitializer extends ChannelInitializer<SocketChannel> {

    private final AuthHandshakeHandler authHandshakeHandler;
    private final WebSocketHandler webSocketHandler;
    private final ExceptionHandler exceptionHandler;
    private final HeartbeatHandler heartbeatHandler;
    private final ProtocolEncoder protocolEncoder;

    public WebSocketChannelInitializer(AuthHandshakeHandler authHandshakeHandler,
                                       WebSocketHandler webSocketHandler,
                                       ExceptionHandler exceptionHandler,
                                       HeartbeatHandler heartbeatHandler,
                                       ProtocolEncoder protocolEncoder) {
        this.authHandshakeHandler = authHandshakeHandler;
        this.webSocketHandler = webSocketHandler;
        this.exceptionHandler = exceptionHandler;
        this.heartbeatHandler = heartbeatHandler;
        this.protocolEncoder = protocolEncoder;
    }

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        pipeline.addLast(new HttpServerCodec());
        // 添加自定义鉴权处理器（必须在握手处理器之前）
        pipeline.addLast(authHandshakeHandler);
        pipeline.addLast(new WebSocketServerProtocolHandler("/chat"));
        pipeline.addLast(protocolEncoder);
        pipeline.addLast(new ProtocolDecoder());
        pipeline.addLast(webSocketHandler);
        pipeline.addLast(new IdleStateHandler(RedisConfig.TIMEOUT_IM_HEARTBEAT, 0, 0));
        pipeline.addLast(heartbeatHandler);
        pipeline.addLast(exceptionHandler); // 添加异常处理器
    }
}
